﻿using System.Collections.Generic;
using System.IO;

namespace Brain.IO
{
    public static class BinaryJoin
    {
        #region Convert To Binary
        /// <summary>
        /// Converts to only one (1) binary file, all the files 
        /// inside the desired directory
        /// </summary>
        /// <param name="dir">The Directory you want to Convert</param>
        /// <param name="destination">The Destination place for the Binary File</param>
        /// <param name="LoopDirectories">If it should loop Directories</param>
        public static void DirectoryToBinary(string dir, string destination, bool LoopDirectories)
        {
#if !SILVERLIGHT
            DirectoryInfo directory = new DirectoryInfo(dir);
            List<FileInfo> Files = new List<FileInfo>();
            GetFilesInsideDir(Files, directory, LoopDirectories);

            List<BinaryFile> BinaryFiles = new List<BinaryFile>();
            // Get Byte Arrays
            for (int i = 0; i < Files.Count; i++)
            {
                BinaryFile file = GetBynaryFile(Files[i]);
                file.FileName = file.FileName.Replace(dir, "");
                BinaryFiles.Add(file);
            }

            int NumberOfFiles = BinaryFiles.Count;

            using (FileStream fs = new FileStream(destination, FileMode.Create))
            {
                BinaryWriter writer = new BinaryWriter(fs);
                writer.Write("BRAINv");
                writer.Write(0.1f);
                writer.Write(NumberOfFiles);

                for (int i = 0; i < NumberOfFiles; i++)
                {
                    writer.Write(BinaryFiles[i].Bytes.Length);
                    writer.Write(BinaryFiles[i].FileName);
                    writer.Write(BinaryFiles[i].Bytes);
                }
            }
#endif
        }
        private static void GetFilesInsideDir(List<FileInfo> list, DirectoryInfo info, bool loopDir)
        {
#if !SILVERLIGHT
            FileInfo[] files = info.GetFiles();

            for (int i = 0; i < files.Length; i++)
                list.Add(files[i]);

            if (loopDir)
            {
                DirectoryInfo[] directories = info.GetDirectories();
                for (int i = 0; i < directories.Length; i++)
                    GetFilesInsideDir(list, directories[i], loopDir);
            }
#endif
        }
        private static BinaryFile GetBynaryFile(FileInfo info)
        {
#if !SILVERLIGHT
            BinaryFile file = new BinaryFile();

            byte[] buff = null;
            using (FileStream fs = new FileStream(info.FullName, FileMode.Open, FileAccess.Read))
            {
                BinaryReader br = new BinaryReader(fs);
                long numBytes = new FileInfo(info.FullName).Length;
                buff = br.ReadBytes((int)numBytes);

                file.Bytes = buff;
                file.FileName = info.FullName;
            }

            return file;
#else
            return null;
#endif
        }

        #endregion

        #region Binary to Files

        public static void BinaryToFiles(string LarBinaryFile, string DestinationFolder)
        {
#if !SILVERLIGHT
            if (!Directory.Exists(DestinationFolder))
                Directory.CreateDirectory(DestinationFolder);

            List<BinaryFile> Files = new List<BinaryFile>();

            using (FileStream fs = new FileStream(LarBinaryFile, FileMode.Open, FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(fs);
                string version = reader.ReadString();
                float v = reader.ReadSingle();

                int NumberOfFiles = reader.ReadInt32();

                for (int i = 0; i < NumberOfFiles; i++)
                {
                    int FileBytes = reader.ReadInt32();
                    string fileName = reader.ReadString();
                    byte[] array = reader.ReadBytes(FileBytes);
                    BinaryFile file = new BinaryFile();

                    if (fileName.StartsWith("\\"))
                    {
                        fileName = fileName.Remove(0, 1);
                    }
                    file.FileName = Path.Combine(DestinationFolder, fileName);
                    file.Bytes = array;
                    Files.Add(file);
                }
            }

            for (int i = 0; i < Files.Count; i++)
            {
                TransformBinaryFileInFile(Files[i]);
            }
#endif
        }
        private static void TransformBinaryFileInFile(BinaryFile file)
        {
#if !SILVERLIGHT
            string p = Path.GetDirectoryName(file.FileName);
            if (!Directory.Exists(p))
            {
                Directory.CreateDirectory(p);
            }
            using (FileStream fs = new FileStream(file.FileName, FileMode.Create))
            {
                BinaryWriter writer = new BinaryWriter(fs);

                writer.Write(file.Bytes);
            }
#endif
        }
        #endregion
    }
}
